﻿using Sage.CloudStorage.Qiniu.Upload;
using System.Text;

namespace Sage.CloudStorage.Qiniu.Utils
{
    /// <summary>
    /// 七牛云工具类
    /// 提供各种实用的工具方法
    /// </summary>
    public static class QiniuUtils
    {
        /// <summary>
        /// 对对象名称进行URL安全的Base64编码
        /// </summary>
        public static string EncodeObjectName(string objectName)
        {
            ArgumentException.ThrowIfNullOrEmpty(objectName, nameof(objectName));

            var bytes = Encoding.UTF8.GetBytes(objectName);
            return Convert.ToBase64String(bytes)
                .Replace('+', '-')
                .Replace('/', '_')
                .TrimEnd('=');
        }

        /// <summary>
        /// 编码Entry URI（用于持久化处理saveas指令）
        /// </summary>
        public static string EncodeEntryURI(string bucket, string key)
        {
            ArgumentException.ThrowIfNullOrEmpty(bucket, nameof(bucket));
            ArgumentException.ThrowIfNullOrEmpty(key, nameof(key));

            return EncodeObjectName($"{bucket}:{key}");
        }

        /// <summary>
        /// 解码对象名称
        /// </summary>
        public static string DecodeObjectName(string encodedObjectName)
        {
            ArgumentException.ThrowIfNullOrEmpty(encodedObjectName, nameof(encodedObjectName));

            var base64 = encodedObjectName.Replace('-', '+').Replace('_', '/');
            var padding = 4 - base64.Length % 4;
            if (padding != 4)
            {
                base64 += new string('=', padding);
            }

            var bytes = Convert.FromBase64String(base64);
            return Encoding.UTF8.GetString(bytes);
        }

        /// <summary>
        /// 根据文件扩展名获取MIME类型
        /// </summary>
        public static string GetMimeType(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                return "application/octet-stream";

            var extension = Path.GetExtension(fileName).ToLowerInvariant();
            return extension switch
            {
                // 图片格式
                ".jpg" or ".jpeg" => "image/jpeg",
                ".png" => "image/png",
                ".gif" => "image/gif",
                ".bmp" => "image/bmp",
                ".webp" => "image/webp",
                ".ico" => "image/x-icon",
                ".svg" => "image/svg+xml",
                ".tiff" or ".tif" => "image/tiff",

                // 视频格式
                ".mp4" => "video/mp4",
                ".avi" => "video/x-msvideo",
                ".mov" => "video/quicktime",
                ".wmv" => "video/x-ms-wmv",
                ".flv" => "video/x-flv",
                ".mkv" => "video/x-matroska",
                ".webm" => "video/webm",
                ".m4v" => "video/x-m4v",

                // 音频格式
                ".mp3" => "audio/mpeg",
                ".wav" => "audio/wav",
                ".flac" => "audio/flac",
                ".aac" => "audio/aac",
                ".ogg" => "audio/ogg",
                ".m4a" => "audio/x-m4a",
                ".wma" => "audio/x-ms-wma",

                // 文档格式
                ".pdf" => "application/pdf",
                ".doc" => "application/msword",
                ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                ".xls" => "application/vnd.ms-excel",
                ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                ".ppt" => "application/vnd.ms-powerpoint",
                ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",

                // 压缩格式
                ".zip" => "application/zip",
                ".rar" => "application/x-rar-compressed",
                ".7z" => "application/x-7z-compressed",
                ".tar" => "application/x-tar",
                ".gz" => "application/gzip",

                // 文本格式
                ".txt" => "text/plain",
                ".html" => "text/html",
                ".css" => "text/css",
                ".js" => "application/javascript",
                ".json" => "application/json",
                ".xml" => "application/xml",

                // 默认
                _ => "application/octet-stream"
            };
        }

        /// <summary>
        /// 格式化字节数为可读格式
        /// </summary>
        public static string FormatBytes(long bytes, int decimalPlaces = 1)
        {
            if (bytes == 0) return "0 B";

            string[] suffixes = ["B", "KB", "MB", "GB", "TB", "PB"];
            double size = Math.Abs(bytes);
            int suffixIndex = 0;

            while (size >= 1024 && suffixIndex < suffixes.Length - 1)
            {
                size /= 1024;
                suffixIndex++;
            }

            var format = decimalPlaces > 0 ? $"F{decimalPlaces}" : "F0";
            var result = size.ToString(format) + " " + suffixes[suffixIndex];

            return bytes < 0 ? "-" + result : result;
        }

        /// <summary>
        /// 根据文件大小智能推荐分片大小
        /// </summary>
        public static int GetRecommendedChunkSize(long fileSize)
        {
            const int MB = 1024 * 1024;

            return fileSize switch
            {
                < 50L * MB => 2 * MB,      // <50MB: 2MB分片
                < 500L * MB => 4 * MB,     // <500MB: 4MB分片
                < 2048L * MB => 8 * MB,    // <2GB: 8MB分片
                _ => 16 * MB               // >=2GB: 16MB分片
            };
        }

        /// <summary>
        /// 验证分片参数的有效性
        /// </summary>
        public static (bool IsValid, string Message) ValidateChunkParameters(long fileSize, int chunkSize)
        {
            if (fileSize <= 0)
                return (false, "文件大小必须大于0");

            if (chunkSize < QiniuMultipartUploadService.MinChunkSize)
                return (false, $"分片大小不能小于{FormatBytes(QiniuMultipartUploadService.MinChunkSize)}");

            if (chunkSize > QiniuMultipartUploadService.MaxChunkSize)
                return (false, $"分片大小不能大于{FormatBytes(QiniuMultipartUploadService.MaxChunkSize)}");

            var partCount = (int)Math.Ceiling((double)fileSize / chunkSize);
            if (partCount > QiniuMultipartUploadService.MaxPartNumber)
            {
                var recommendedChunkSize = (long)Math.Ceiling((double)fileSize / QiniuMultipartUploadService.MaxPartNumber);
                return (false, $"分片数量({partCount})超过限制({QiniuMultipartUploadService.MaxPartNumber})，建议分片大小至少为{FormatBytes(recommendedChunkSize)}");
            }

            return (true, "参数有效");
        }
    }

    /// <summary>
    /// 文件类型工具类
    /// </summary>
    public static class FileTypeUtils
    {
        /// <summary>
        /// 判断是否为图片文件
        /// </summary>
        public static bool IsImageFile(string fileName)
        {
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            return ext is ".jpg" or ".jpeg" or ".png" or ".gif" or ".bmp" or ".webp" or ".svg" or ".ico" or ".tiff" or ".tif";
        }

        /// <summary>
        /// 判断是否为视频文件
        /// </summary>
        public static bool IsVideoFile(string fileName)
        {
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            return ext is ".mp4" or ".avi" or ".mov" or ".wmv" or ".flv" or ".mkv" or ".webm" or ".m4v";
        }

        /// <summary>
        /// 判断是否为音频文件
        /// </summary>
        public static bool IsAudioFile(string fileName)
        {
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            return ext is ".mp3" or ".wav" or ".flac" or ".aac" or ".ogg" or ".m4a" or ".wma";
        }

        /// <summary>
        /// 判断是否为文档文件
        /// </summary>
        public static bool IsDocumentFile(string fileName)
        {
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            return ext is ".pdf" or ".doc" or ".docx" or ".xls" or ".xlsx" or ".ppt" or ".pptx" or ".txt";
        }

        /// <summary>
        /// 获取文件类型分类
        /// </summary>
        public static string GetFileCategory(string fileName)
        {
            if (IsImageFile(fileName)) return "图片";
            if (IsVideoFile(fileName)) return "视频";
            if (IsAudioFile(fileName)) return "音频";
            if (IsDocumentFile(fileName)) return "文档";
            return "其他";
        }
    }
}
